/******************** (C) COPYRIGHT 2013 SONiX *******************************
* COMPANY:			SONiX
* DATE:					2013/12
* AUTHOR:				SA1
* IC:						SN32F240/230/220
* DESCRIPTION:	Flash related functions.
*____________________________________________________________________________
* REVISION	Date				User		Description
* 1.0				2013/12/17	SA1			First release
*
*____________________________________________________________________________
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS TIME TO MARKET.
* SONiX SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL 
* DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF SUCH SOFTWARE
* AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN 
* IN CONNECTION WITH THEIR PRODUCTS.
*****************************************************************************/

/*_____ I N C L U D E S ____________________________________________________*/
#include "Flash.h"
#include "WDT.h"
#include "..\Project\FlashRom.h"
#include "..\KB\KB_BT.h"

/*_____ D E C L A R A T I O N S ____________________________________________*/
uint8_t wFLASH_PGRAM[1024];


/*_____ D E F I N I T I O N S ______________________________________________*/


/*_____ M A C R O S ________________________________________________________*/


/*_____ F U N C T I O N S __________________________________________________*/
extern void SubFLASH_ProgramPage (void);
/*****************************************************************************
* Function		: FLASH_EraseSector
* Description	: Erase assigned sector address in Flash ROM
* Input			: adr - Sector start address
* Output		: None
* Return		: None
* Note			: None
*****************************************************************************/
void FLASH_EraseSector (uint32_t adr)
{
	if(adr<ROM_USER_ADDR)
		return;
/*
 	SN_FLASH->CTRL = FLASH_PER;						// Page Erase Enabled
	SN_FLASH->ADDR = adr;									// Page Address

	FLASH_WAIT_FOR_DONE	
	
	SN_FLASH->CTRL |= FLASH_START;				// Start Erase

	FLASH_WAIT_FOR_DONE
*/
	__WDT_FEED_VALUE;						//Feed WatchDog
 	SN_FLASH->CTRL = FLASH_PER;					// Page Erase Enabled
	SN_FLASH->ADDR = adr;									// Page Address  
//	SN_FLASH->CTRL |= FLASH_STARTE;				// Start Erase

//	while ((SN_FLASH->STATUS & FLASH_BUSY) == FLASH_BUSY);
	
	//** Disable all Interrupts during Code excuted in Ram.
	NVIC_DisableIRQ(USB_IRQn);
	NVIC_DisableIRQ(CT16B3_IRQn);
	NVIC_ClearPendingIRQ(CT16B3_IRQn);
	NVIC_DisableIRQ(SPI0_IRQn);	
	NVIC_ClearPendingIRQ(SPI0_IRQn);	
	SysTick->CTRL = 0;	
	__WDT_DISABLE;
	//** Excuting Flash Program Function in Ram 
	SubFLASH_ProgramPage();
	
	//** After excuting ISP,to enable all Interrupts and excute code in Rom.
	if(rSys_mode == SYS_USB_MODE)
	{
		NVIC_ClearPendingIRQ(USB_IRQn);
		NVIC_EnableIRQ(USB_IRQn);
	}
	NVIC_ClearPendingIRQ(CT16B3_IRQn);
	NVIC_EnableIRQ(CT16B3_IRQn);
	NVIC_ClearPendingIRQ(SPI0_IRQn);	
	NVIC_EnableIRQ(SPI0_IRQn);
	SysTick->CTRL = 7;	
	WDT_Init();	
}


/*****************************************************************************
* Function		: Flash_ProgramPage
* Description	: Program assigned page in Flash ROM
* Input			: adr - Page start address (word-alignment) of Flash
*				  		sz - Content size to be programmed (Bytes)
*				  		pBuf - pointer to the Source data
* Output		: None
* Return		: OK or FAIL
* Note			: None
*****************************************************************************/
uint32_t FLASH_ProgramPage_Byte(volatile uint32_t adr, volatile uint32_t sz, uint8_t *pBuf)
{
	uint32_t wPutInRom;
	if(adr<ROM_USER_ADDR)
		return 1;
	
	sz = (sz + 3) & ~3;											// Adjust size for Words
	
	SN_FLASH->STATUS  &= ~(FLASH_ERR);			// Reset Error Flags
	
	SN_FLASH->CTRL = FLASH_PG;                  // Programming Enabled
	
	SN_FLASH->ADDR = adr;
	
	while (sz)
	{
		wPutInRom = *((uint8_t *)pBuf);
		wPutInRom |= ((*((uint8_t *)(pBuf+1)))<<8);
		wPutInRom |= ((*((uint8_t *)(pBuf+2)))<<16);
		wPutInRom |= ((*((uint8_t *)(pBuf+3)))<<24);

		SN_FLASH->DATA = wPutInRom;
		if ((((adr >> 2) % 2) == 1) || (sz == 4)) 
		{
			SN_FLASH->CTRL |= FLASH_START;			// Start Program
			FLASH_WAIT_FOR_DONE;

			// FLASH_ERR = 0x04
			if (SN_FLASH->STATUS & FLASH_ERR) {	// Check for Errors
				return (FAIL);												// Failed
			}
    }
		
		// Go to next Word
		adr += 4;
		pBuf += 4;
		sz  -= 4;
		
	  if ((((adr >> 2) % 2) == 0)) 
		{
			SN_FLASH->CTRL = FLASH_PG;					// Programming Enabled
		  SN_FLASH->ADDR = adr;
		}
	}

	return (OK);
}

/*****************************************************************************
** Descriptions:		FLASH_ProgramPage
**
** parameters:			starting rom address to program , program size, source ram pointer to program
** Returned value:	0: Pass, 1: Fail
** Descriptor:			
***************************************************************************/
int FLASH_ProgramPage (uint32_t adr, uint32_t sz, uint32_t* buf) 
{ 
	if(adr<ROM_USER_ADDR)
		return 1;
	
  SN_FLASH->STATUS  &= ~(FLASH_ERR);								// Reset Error Flags

	SN_FLASH->CTRL  =  FLASH_PG;											// Programming Enabled
	SN_FLASH->ADDR  =  adr;
	FLASH_WAIT_FOR_DONE
	
  while (sz) 
	{
    SN_FLASH->DATA  = (*buf);
    __nop();
	 buf++;
	 sz--;
  }
	
	SN_FLASH->CTRL   |= FLASH_START;                       

	FLASH_WAIT_FOR_DONE

	if (SN_FLASH->STATUS & FLASH_ERR)
      return (1);																			// Failed

  return (0);																					// Done
}
/*****************************************************************************
* Function		: Flash_ProgramPage
* Description	: Program assigned page in Flash ROM
* Input			: adr - Page start address (word-alignment) of Flash
*				  		sz - Content size to be programmed (Bytes)
*				  		pBuf - pointer to the Source data
* Output		: None
* Return		: OK or FAIL
* Note			: None
*****************************************************************************/
uint32_t FLASH_ProgramPage_Word(volatile uint32_t adr, volatile uint32_t sz, uint32_t *pBuf)
{
	uint32_t wPutInRom;
	if(adr<ROM_USER_ADDR)
		return 1;
	
	SN_FLASH->STATUS  &= ~(FLASH_ERR);			// Reset Error Flags
	
	SN_FLASH->CTRL = FLASH_PG;                  // Programming Enabled
	
	SN_FLASH->ADDR = adr;
	
	while (sz)
	{
		wPutInRom = *((uint32_t *)pBuf);
		SN_FLASH->DATA = wPutInRom;
		if ((((adr >> 2) % 2) == 1) || (sz == 1)) 
		{
			SN_FLASH->CTRL |= FLASH_START;			// Start Program
			FLASH_WAIT_FOR_DONE;

			// FLASH_ERR = 0x04
			if (SN_FLASH->STATUS & FLASH_ERR) {	// Check for Errors
				return (FAIL);												// Failed
			}
    }
		
		// Go to next Word
		adr += 4;
		pBuf += 1;
		sz  -= 1;
		
	  if ((((adr >> 2) % 2) == 0)) 
		{
			SN_FLASH->CTRL = FLASH_PG;					// Programming Enabled
		  SN_FLASH->ADDR = adr;
		}
	}

	return (OK);
}


